/*
 * Copyright 2012 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudgettable.client.ui.grid.cell.date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;

import finbudgettable.client.ui.grid.CellGrid;
import finbudgettable.client.ui.grid.DateUtils;
import finbudgettable.client.ui.grid.cell.ContextMenu;
import finbudgettable.client.ui.grid.cell.ContextMenuPopupPanel;

import java.util.Date;

public class DateContextMenu implements ContextMenu<Date> {

    static final String[] QUARTERS = {"I", "II", "III", "IV"};

    static final MenuConstants CONSTANTS = GWT.create(MenuConstants.class);

    private final CellGrid grid;
    protected final String fieldName;

    private MenuBar menu;
    private PopupPanel popupPanel;

    private final Command lastYearCommand = new Command() {
        @Override
        public void execute() {
            Date now = new Date();
            Date beginDate = DateUtils.getFirstDayOfYear(DateUtils.addYears(now, -1));
            Date endDate = DateUtils.addYears(beginDate, 1);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command thisYearCommand = new Command() {
        @Override
        public void execute() {
            Date now = new Date();
            Date beginDate = DateUtils.getFirstDayOfYear(now);
            Date endDate = DateUtils.addYears(beginDate, 1);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command lastQrCommand = new Command() {
        @Override
        public void execute() {
            Date date = new Date();
            CalendarUtil.addMonthsToDate(date, -3);
            int qr = DateUtils.getMonth(date) / 3;
            Date beginDate = DateUtils.getFirstDayOfYear(date);
            CalendarUtil.addMonthsToDate(beginDate, 3 * qr);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addMonthsToDate(endDate, 3);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command thisQrCommand = new Command() {
        @Override
        public void execute() {
            Date now = new Date();
            int qr = DateUtils.getMonth(now) / 3;
            Date beginDate = DateUtils.getFirstDayOfYear(now);
            CalendarUtil.addMonthsToDate(beginDate, 3 * qr);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addMonthsToDate(endDate, 3);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command inYearCommand = new Command() {
        @Override
        public void execute() {
            Date date = CalendarUtil.copyDate(currentValue);
            Date beginDate = DateUtils.getFirstDayOfYear(date);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addMonthsToDate(endDate, 12);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command inQrYrCommand = new Command() {
        @Override
        public void execute() {
            Date beginDate = CalendarUtil.copyDate(currentValue);
            int qr = DateUtils.getMonth(beginDate) / 3;
            beginDate = DateUtils.getFirstDayOfYear(beginDate);
            CalendarUtil.addMonthsToDate(beginDate, 3 * qr);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addMonthsToDate(endDate, 3);
            applyFilter(beginDate, endDate);
        }
    };

    private final Command inMnYrCommand = new Command() {
        @Override
        public void execute() {
            Date beginDate = CalendarUtil.copyDate(currentValue);
            int month = DateUtils.getMonth(beginDate);
            beginDate = DateUtils.getFirstDayOfYear(beginDate);
            CalendarUtil.addMonthsToDate(beginDate, month);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addMonthsToDate(endDate, 1);
            applyFilter(beginDate, endDate);
        }
    };

    private void applyFilter(Date beginDate, Date endDate) {
        grid.getFilter().setFilter(fieldName, createFilter(beginDate, endDate));
        grid.filter();
        popupPanel.hide();
        grid.setFocus(true);
    }

    protected DatePeriodFilter createFilter(Date beginDate, Date endDate) {
        return new DatePeriodFilter(fieldName, beginDate, endDate);
    }

    private final Command inDayCommand = new Command() {
        @Override
        public void execute() {
            Date beginDate = CalendarUtil.copyDate(currentValue);
            Date endDate = CalendarUtil.copyDate(beginDate);
            CalendarUtil.addDaysToDate(endDate, 1);
            applyFilter(beginDate, endDate);
        }
    };

    public DateContextMenu(CellGrid grid, String fieldName) {
        this.grid = grid;
        this.fieldName = fieldName;
    }

    private void createMenu(Date value) {
        popupPanel = new ContextMenuPopupPanel(grid);
        menu = new MenuBar(true);
        menu.setAutoOpen(false);
        menu.addStyleName(ContextMenuPopupPanel.RESOURCES.style().bCellContextMenu());
        menu.addItem(CONSTANTS.lastYr(), lastYearCommand);
        menu.addItem(CONSTANTS.thisYr(), thisYearCommand);
        menu.addItem(CONSTANTS.lastQr(), lastQrCommand);
        menu.addItem(CONSTANTS.thisQr(), thisQrCommand);
        if (value != null) {
            menu.addSeparator();
            menu.addItem(CONSTANTS.inYr(DateUtils.getYear(value)), inYearCommand);
            menu.addItem(CONSTANTS.inQrYr(QUARTERS[DateUtils.getMonth(value) / 3], DateUtils.getYear(value)), inQrYrCommand);
            menu.addItem(CONSTANTS.inMnYr(Integer.toString(DateUtils.getMonth(value) + 1), DateUtils.getYear(value)), inMnYrCommand);
            menu.addItem(CONSTANTS.date(DateUtils.dateToString(value)), inDayCommand);
        }
        popupPanel.add(menu);
/*        popupPanel.addCloseHandler(new CloseHandler<PopupPanel>() {
            @Override
            public void onClose(CloseEvent<PopupPanel> event) {
                if (!event.isAutoClosed()) {
                    if (lastParent != null) {
                        lastParent.focus();
                    }
                }
                lastParent = null;
            }
        });*/
    }

    private Date currentValue;

    @Override
    public void show(int x, int y, Element parent, Date value) {
        currentValue = value;
        createMenu(value);
        popupPanel.setPopupPosition(x, y);
        popupPanel.show();
        menu.focus();
    }
}
